using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Audio;

namespace ADiKt {
    abstract class MenuScreen : Screen {
        List<Entry> menuEntries = new List<Entry>();
        protected int selectedEntry = 0;
        string menuTitle;

        protected IList<Entry> MenuEntries {
            get { return menuEntries; }
        }

        public MenuScreen(string menuTitle) {
            this.menuTitle = menuTitle;
            TransitionOnTime = TimeSpan.FromSeconds(0.5);
            TransitionOffTime = TimeSpan.FromSeconds(0.5);
        }

        public override void HandleInput(InputState input) {
            // Move up/down?
            if (input.IsMenuUp(ControllingPlayer)) {
                ScreenManager.MenuChangeSound.Play(0.3f,0f,0f);
                selectedEntry = (selectedEntry-- <= 0) ? menuEntries.Count-1 : selectedEntry--;
            }else if (input.IsMenuDown(ControllingPlayer)) {
                ScreenManager.MenuChangeSound.Play(0.3f, 0f, 0f);
                selectedEntry = (selectedEntry++ >= menuEntries.Count - 1) ? 0 : selectedEntry++;
            }

            PlayerIndex playerIndex;
            if (input.IsMenuCancel(ControllingPlayer, out playerIndex)) {
                OnCancel(playerIndex);

            }else if (menuEntries[selectedEntry].GetType() == typeof(MenuEntry)) {
                MenuEntry me = (MenuEntry)menuEntries[selectedEntry];
                if (input.IsMenuSelect(ControllingPlayer, out playerIndex)) {
                    ScreenManager.MenuSelectSound.Play();
                    me.OnSelectEntry(playerIndex);
                }

            } else if (menuEntries[selectedEntry].GetType() == typeof(SpinEntry)) {
                SpinEntry se = (SpinEntry)menuEntries[selectedEntry];
                if (input.IsMenuNext(ControllingPlayer, out playerIndex)) {
                    ScreenManager.MenuSpinSound.Play();
                    se.OnNext();
                } else if (input.IsMenuLast(ControllingPlayer, out playerIndex)) {
                    ScreenManager.MenuSpinSound.Play();
                    se.OnLast();
                }
            }
        }

        //standared ESC action, can be overriden
        protected virtual void OnCancel(PlayerIndex playerIndex) {
            ScreenManager.MenuSelectSound.Play();
            ExitScreen();
        }

        protected void OnCancel(object sender, PlayerIndexEventArgs e) {
            OnCancel(e.PlayerIndex);
        }

        protected virtual void UpdateMenuEntryLocations() {
            // Make the menu slide into place during transitions, using a power curve
            float transitionOffset = (float)Math.Pow(TransitionPosition, 2);

            // start at Y = 175; each X value is generated per entry
            Vector2 position = new Vector2(0f, 175f);

            // update each menu entry's location in turn
            for (int i = 0; i < menuEntries.Count; i++) {
                Entry menuEntry = menuEntries[i];

                // each entry is to be centered horizontally
                position.X = ScreenManager.GraphicsDevice.Viewport.Width / 2 - menuEntry.GetWidth(this) / 2;

                if (ScreenState == ScreenState.TransitionOn)
                    position.X -= transitionOffset * 256;
                else
                    position.X += transitionOffset * Globals.width/2;

                menuEntry.Position = position;
                position.Y += menuEntry.GetHeight(this);
            }
        }

        public override void Update(GameTime gameTime, bool otherScreenHasFocus, bool coveredByOtherScreen) {
            base.Update(gameTime, otherScreenHasFocus, coveredByOtherScreen);
            for (int i = 0; i < menuEntries.Count; i++) {
                bool isSelected = IsActive && (i == selectedEntry);
                menuEntries[i].Update(this, isSelected, gameTime);
            }
        }

        public override void Draw(GameTime gameTime) {
            UpdateMenuEntryLocations();

            GraphicsDevice graphics = ScreenManager.GraphicsDevice;
            SpriteBatch spriteBatch = ScreenManager.SpriteBatch;
            SpriteFont font = ScreenManager.Font;

            spriteBatch.Begin();

            for (int i = 0; i < menuEntries.Count; i++) {
                Entry menuEntry = menuEntries[i];
                bool isSelected = IsActive && (i == selectedEntry);
                menuEntry.Draw(this, isSelected, gameTime);
            }

            // Make the menu slide into place during transitions, using a power curve
            float transitionOffset = (float)Math.Pow(TransitionPosition, 2);

            // Draw the menu title centered on the screen
            Vector2 titlePosition = new Vector2(graphics.Viewport.Width / 2, 80);
            Vector2 titleOrigin = font.MeasureString(menuTitle) / 2;
            Color titleColor = new Color(92, 92, 92) * TransitionAlpha;
            float titleScale = 2.0f;
            titlePosition.Y -= transitionOffset * 100;
            spriteBatch.DrawString(font, menuTitle, titlePosition, titleColor, 0, titleOrigin, titleScale, SpriteEffects.None, 0);

            spriteBatch.End();
        }
    }
}